package com.neuralnoise.flickr;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.TreeSet;

import com.aetrion.flickr.Flickr;
import com.aetrion.flickr.REST;
import com.aetrion.flickr.RequestContext;
import com.aetrion.flickr.Transport;
import com.aetrion.flickr.auth.Auth;
import com.aetrion.flickr.auth.Permission;
import com.aetrion.flickr.contacts.ContactsInterface;
import com.aetrion.flickr.groups.pools.PoolsInterface;
import com.aetrion.flickr.people.PeopleInterface;
import com.aetrion.flickr.photos.geo.GeoInterface;
import com.aetrion.flickr.tags.TagsInterface;
import com.aetrion.flickr.urls.UrlsInterface;
import com.neuralnoise.AbstractDriver;
import com.neuralnoise.FlickrDB;
import com.neuralnoise.foaf.core.Person;
import com.neuralnoise.geo.GeoUtils;
import com.neuralnoise.geo.GeoUtils.ServiceType;
import com.neuralnoise.hibernate.flickr.Profile;
import com.neuralnoise.hibernate.flickr.User;
import com.neuralnoise.hibernate.geo.GeoLocation;

public class FlickrDriver extends AbstractDriver<String> {

	protected FlickrProperties properties;

	protected Transport rest;
	protected RequestContext requestContext;

	protected Flickr flickr;
	protected ContactsInterface contactsInterface;
	protected PeopleInterface peopleInterface;
	protected PoolsInterface poolsInterface;
	protected TagsInterface tagsInterface;
	protected UrlsInterface urlsInterface;
	protected GeoInterface geoInterface;
	
	public FlickrDriver(FlickrProperties f) throws Exception {
		this.properties = f;
		
		final String apiKey = f.getApiKey();
		final String secret = f.getSecret();
		final String token = f.getToken();
		
		this.rest = new REST("www.flickr.com");
		
		this.requestContext = RequestContext.getRequestContext();
		Auth auth = new Auth();
		auth.setPermission(Permission.READ);
		auth.setToken(f.getToken());
		this.requestContext.setAuth(auth);
		
		this.flickr = new Flickr(apiKey, secret, this.rest);
		this.contactsInterface = new ContactsInterface(apiKey, secret, this.rest);
		this.peopleInterface = new PeopleInterface(apiKey, secret, this.rest);
		this.poolsInterface = new PoolsInterface(apiKey, secret, this.rest);
		this.tagsInterface = new TagsInterface(apiKey, secret, this.rest);
		this.urlsInterface = new UrlsInterface(apiKey, secret, this.rest);
		this.geoInterface = new GeoInterface(apiKey, secret, this.rest);
	}

	@Override
	public boolean hasUserData(String id) throws Exception {
		boolean ret = false;
		Profile profile = FlickrDB.getProfile(id);
		if (profile != null) {
			ret = true;
		}
		return ret;
	}

	@Override
	public void addUserData(String _user) throws Exception {
		//User user =	
		FlickrDB.toUser(_user);
		com.aetrion.flickr.people.User info = this.peopleInterface.getInfo(_user);
		Collection<String> contacts = null;
		if (info != null) {
			FlickrDB.addProfile(_user, info.getUsername(), info.getRealName(), info.getLocation());
			contacts = this.contactsInterface.getPublicList(_user);
		}
		FlickrDB.addFriendsOf(_user, contacts);
	}

	@Override
	public Collection<String> getConnections(String _user) throws Exception {
		Collection<User> _friends = FlickrDB.getFriendsOf(_user);
		Collection<String> friends = new TreeSet<String>();
		for (User _friend : _friends) {
			friends.add(_friend.getId());
		}
		return friends;
	}
	
	@Override
	public Person toPerson(String id) throws Exception {
		if (!hasUserData(id)) {
			addUserData(id);
		}
		
		Person person = null;
		Profile profile = FlickrDB.getProfile(id);
		if (profile != null ) {
			person = new Person();
			person.setUri("http://semanticflickr.example.org/" + profile.getUser());

			final String name = profile.getName();
			if (name != null) {
				person.addName(name);
			}
			
			Collection<User> friends = FlickrDB.getFriendsOf(id);
			if (friends != null) {
				for (User friend : friends) {
					Person pfriend = new Person();
					pfriend.setUri("http://semanticflickr.example.org/" + friend.getId());
					person.addKnows(pfriend);
				}
			}
			
			final String location = profile.getLocation();
			if (location != null) {
				GeoLocation latlng = GeoUtils.findAddLocation(ServiceType.GOOGLE, location, "en");
				if (latlng != null) {
					person.setLatitude(BigDecimal.valueOf(latlng.getLatitude()));
					person.setLongitude(BigDecimal.valueOf(latlng.getLongitude()));
				}
			}
		}
		
		return person;
	}
	
}
